/******************************************************************
 *
 *    Java Lib For JavaWeb, Powered By Zhejiang hangzhou.
 *
 *    Copyright (c) 2001-2020
 *    http://tankpao.tk/
 *
 *    Package:     tk.tankpao.blast.web.util
 *
 *    Filename:    RequestUtil.java
 *
 *    Description: TODO(用一句话描述该文件做什么)
 *
 *    Copyright:   Copyright (c) 2001-2020
 *
 *    Company:     tankpao.tk
 *
 *    @author:     王志刚
 *
 *    @version:    1.0.0
 *
 *    Create at:   2017年2月9日 下午2:58:02
 *
 *    Revision:
 *
 *    2017年2月9日 下午2:58:02
 *        - first revision
 *
 *****************************************************************/
package tk.tankpao.blast.web.util;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.servlet.http.HttpServletRequest;

/**
 * 
 * @ClassName RequestUtil
 * @Description 请求参数转换工具类
 * @author 王志刚
 * @Date 2017年2月9日 下午2:58:20
 * @version 1.0.0
 */
public class RequestUtil {

	public static String METHOD_POST = "post";
	public static String METHOD_GET = "get";
	
	@SuppressWarnings("unchecked")
	public static <T> T queryStringToBean(Class<T> clazz, HttpServletRequest request) {
		Map<String, Object> params = getQueryParams(request);
		Object target = mapToBean(clazz, params);
		return (T)target;
	}
	
	public static <T> T queryStringToBaseType(String pname, Class<T> clazz, HttpServletRequest request){
		Map<String, Object> params = getQueryParams(request);
		Object target = mapToBaseType(pname, clazz, params);
		return (T)target;
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T mapToBaseType(String pname, Class<T> clazz, Map<String, Object> params){
		Object target = null;
		String typeName = clazz.getName();
		Object pobjects = params.get(pname);
		if(pobjects == null){
			return null;
		}
		String[] values = (String[]) pobjects;
		
		if (typeName.equals("java.lang.String")){
			target = values[0];
		}else if(typeName.equals("java.lang.Integer") || typeName.equals("int")){
			target = values[0]==null?0:Integer.valueOf(values[0]);
		}else if(typeName.equals("java.lang.Long") || typeName.equals("long")){
			target = values[0]==null?0l:Long.valueOf(values[0]);
		}else if(typeName.equals("java.lang.Double") || typeName.equals("double")){
			target = values[0]==null?0d:Double.valueOf(values[0]);
		}else if(typeName.equals("java.lang.Float") || typeName.equals("float")){
			target = values[0]==null?0f:Float.valueOf(values[0]);
		}else if(typeName.equals("java.lang.Short") || typeName.equals("short")){
			target = values[0]==null?0:Short.valueOf(values[0]);
		}else if(typeName.equals("java.lang.Byte") || typeName.equals("byte")){
			target = values[0]==null?0:Byte.valueOf(values[0]);
		}else if(typeName.equals("java.lang.Boolean") || typeName.equals("boolean")){
			target = values[0]==null?0:Boolean.valueOf(values[0]);
		}
		if(target == null){
			return null;
		}
		return (T)target;
	}

	@SuppressWarnings("unchecked")
	public static <T> T mapToBean(Class<T> clazz, Map<String, Object> params) {
		Object target = null;
		try {
			target = Class.forName(clazz.getName()).newInstance();
			Field[] fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				Object value = params.get(field.getName());
				if (value != null) {
					field.setAccessible(true);
					if (field.getClass().isArray()) {
						field.set(target, mapToBaseType(field.getName(), field.getClass(), params));
					} else {
						field.set(target, mapToBaseType(field.getName(), field.getType(), params));
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return (T)target;
	}
	
	@SuppressWarnings("rawtypes")
	public static boolean isBaseTypes(Class clazz){
		String typeName = clazz.getName();
		if (typeName.equals("java.lang.String") 
				|| typeName.equals("java.lang.Integer") || typeName.equals("int")
				|| typeName.equals("java.lang.Long") || typeName.equals("long") 
				|| typeName.equals("java.lang.Double") || typeName.equals("double") 
				|| typeName.equals("java.lang.Float") || typeName.equals("float")
				|| typeName.equals("java.lang.Short") || typeName.equals("short") 
				|| typeName.equals("java.lang.Byte") || typeName.equals("byte") 
				|| typeName.equals("java.lang.Boolean") || typeName.equals("boolean")
				|| typeName.equals("java.lang.Character")) {
			return true;
		} else {
			return false;
		}
	}
	
	public static Map<String, Object> getQueryParams(HttpServletRequest request) {
		Map<String, Object> params = new HashMap<String, Object>();
		try {
//			String queryString = request.getQueryString();
//			if (queryString != null && !queryString.trim().equals("")) {
//				queryString = URLDecoder.decode(queryString, "UTF-8");
//				params.putAll(parseQueryString(queryString));
//			}
			params.putAll(request.getParameterMap());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return params;
	}

	public static Map<String, Object> parseQueryString(String queryString) {
		Map<String, Object> params = new HashMap<String, Object>();
		params = Stream.of(queryString).map(s -> s.split("&")).flatMap(Arrays::stream).map(s -> s.split("="))
				.collect(Collectors.toMap((arr -> arr[0]), (arr -> arr[1])));
		return params;
	}
}
